using System;
using System.Collections;
using System.Collections.Generic;
using System.Html;
using System.Runtime.CompilerServices;
using ThemeChain;

namespace Nsb.Classes
{
    [IgnoreNamespace]
    public static class Uri
    {
        public static readonly Dictionary QueryData = Pairs(Window.Location.Search);

        public static string MasterVersion
        {
            get { return (string) Storage.GetLocal("MasterVersionId") ?? BumpVersion(); }
        }

        public static string Relative(string uri)
        {
            return uri;
        }

        public static bool IsHttp(string uri)
        {
            return ((RegularExpression) Script.Literal(@"/^https?:\/\//i")).Test(uri);
        }

        public static string Uniqueify(string uri)
        {
            return AddPair(Relative(uri), "_", (new Date()).GetTime().ToString());
        }

        public static string Img(string path)
        {
            return Join(ThemeBase.MediaImgUri, path);
        }

        public static string DbPath(string path)
        {
            return DebugJs(Join(ThemeBase.DbPath, path));
        }

        public static string App(string path)
        {
            return DebugJs(Join(ThemeBase.AppUri, path));
        }

        public static string Scripts(string path)
        {
            return DebugJs(Join(ThemeBase.ScriptsUri, path));
        }

        /// <summary>
        /// App without .debug. added to .js files
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        public static string AppNd(string path)
        {
            return Versionize(Join(ThemeBase.AppUri, path));
        }

        /// <summary>
        /// Scripts without .debug. added to .js files
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns></returns>
        public static string ScriptsNd(string path)
        {
            return Versionize(Join(ThemeBase.ScriptsUri, path));
        }

        public static string DebugJs(string uri)
        {
            return Versionize(ThemeBase.DevServer ? Relative(uri).ReplaceRegex((RegularExpression)Script.Literal(@"/\.js$|\.js(\?)/"), ".debug.js$1") : Relative(uri));
        }

        public static string Smart(string path)
        {
            if (path.IndexOf("Scripts/") == 0)
                return Scripts(path.Substr(8));
            if (path.IndexOf("data/") == 0)
                return App(path.Substr(5));
            if (path.IndexOf("app/") == 0)
                return App(path.Substr(4));
            return DebugJs(path);
        }

        /// <summary>
        /// All of the uri before the question mark (?)
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <returns>Full uri path</returns>
        public static string Path(string uri)
        {
            return (Relative(uri) ?? "").Split("?")[0];
        }

        public static string Query(string uri)
        {
            return (uri ?? "").Split("?")[1] ?? "";
        }

        public static string Front(string uri)
        {
            string f = Path(uri);
            return f.Substr(0, f.Length - End(uri).Length - 1);
        }

        public static string End(string uri)
        {
            string[] p = Path(uri).Split("/");
            return p[p.Length - 1];
        }

        public static string Ext(string uri)
        {
            string[] sa = End(uri).Split(".");
            return sa.Length == 1 ? "" : "." + sa[sa.Length - 1];
        }

        public static string RemoveExt(string name)
        {
            name = name ?? "";
            string[] ns = name.Split(".");
            return ns.Length > 1 ? name.Substr(0, name.Length - ns[ns.Length - 1].Length - 1) : name;
        }

        [AlternateSignature]
        public static extern string Join(string u1, string u2);

        [AlternateSignature]
        public static extern string Join(string u1, string u2, string u3);

        /// <summary>
        /// Joins paths with slashes.
        /// </summary>
        /// <param name="u1">path part</param>
        /// <param name="u2">path part</param>
        /// <param name="u3">path part</param>
        /// <param name="u4">path part</param>
        /// <returns></returns>
        public static string Join(string u1, string u2, string u3, string u4)
        {
            bool s1 = !String.IsNullOrEmpty(u1);
            bool s2 = !String.IsNullOrEmpty(u2);
            bool s3 = !String.IsNullOrEmpty(u3);
            bool s4 = !String.IsNullOrEmpty(u4);
            return
                (
                    (!s1 ? "" : u1.Trim()) +
                    (!s2 ? "" : (s1 ? "/" : "") + u2.Trim()) +
                    (!s3 ? "" : (s1 || s2 ? "/" : "") + u3.Trim()) +
                    (!s4 ? "" : (s1 || s2 || s3 ? "/" : "") + u4.Trim())
                )
                .ReplaceRegex((RegularExpression) Script.Literal(@"/\/+/g"), "/")
                .ReplaceRegex((RegularExpression)Script.Literal(@"/^(https?:)\//g"), "$1//")
                ;
        }

        public static Dictionary Pairs(string txt)
        {
            Dictionary d = new Dictionary();
            if (txt.Substr(0, 1) == "?")
                txt = txt.Substr(1);
            string[] pairs = txt.Split("&");
            if (pairs.Length > 0)
                foreach (string pair in pairs)
                {
                    string[] p = pair.Split("=");
                    if (String.IsNullOrEmpty(p[0]))
                        continue;
                    if (p.Length >= 2)
                        d[p[0].DecodeUriComponent()] = pair.Substr(p[0].Length + 1).DecodeUriComponent();
                    else
                        d[p[0].DecodeUriComponent()] = "";
                }
            return d;
        }

        public static string GetValue(string url, string nm)
        {
            try
            {
                return (string) Pairs(Query(url))[nm];
            }
            catch
            {
                return null;
            }
        }

        public static string Serialize(Dictionary d)
        {
            string ot = "";
            foreach (KeyValuePair<string, object> pair in d)
            {
                ot += (ot.Length > 0 ? "&" : "") + pair.Key.EncodeUriComponent() + "=" + (pair.Value ?? "").ToString().EncodeUriComponent();
            }
            return ot;
        }

        public static string AddPair(string uri, string name, string value)
        {
            Dictionary d = Pairs(Query(uri));
            d[name] = value;
            return Path(uri) + "?" + Serialize(d);
        }

        public static string ParseFromCss(string css)
        {
            return (((RegularExpression) Script.Literal(@"/url\((.*)\)/g")).Exec(css ?? "")[1] ?? "").Trim();
        }

        /*
        public static string TrimEndSlash(string uri)
        {
            return (uri ?? "").ReplaceRegex((RegularExpression) Script.Literal(@"/^\s+|\/$|\s+$/g"), "");
        }

        public static string TrimFrontSlash(string uri)
        {
            return (uri ?? "").ReplaceRegex((RegularExpression)Script.Literal(@"/^\s+|^\/|\s+$/g"), "");
        }

        public static string TrimSlashes(string uri)
        {
            return (uri ?? "").ReplaceRegex((RegularExpression)Script.Literal(@"/^\s+|^\/|\/$|\s+$/g"), "");
        }
        */

        public static string BumpVersion()
        {
            string v = (new Date()).GetTime().ToString();
            Storage.SetLocal("MasterVersionId", v);
            return v;
        }

        public static string Versionize(string uri)
        {
            uri = Relative(uri) ?? "";
            if (uri.IndexOf(".") == -1)
                return uri;
            RegularExpression rx = (RegularExpression) Script.Literal(@"/url\([^\)]+\)/");
            if (rx.Test(uri))
                return uri.ReplaceRegex(rx, "url(" + AddPair(ParseFromCss(uri), "_", MasterVersion) + ")");
            return AddPair(uri, "_", MasterVersion);
        }
    }
}